Flutter 内嵌原生视图能力
在 Flutter 开发中,有一些原生开发的视图(Android/iOS),这些视图在 Flutter 中该如何使用呢?
有一种直观的想法,直接用 Flutter 开发一遍不就行了吗?
这是最理想的方案。然而,很多时候,原生视图本身比较复杂,比如 WebView、地图、播放器、游戏引擎,我们很难用 Flutter 将其开发一遍。
因此,另外一种想法,能否将这些原生视图“嵌”入 Flutter 当中,实现复用呢?
答案是支持,Flutter 通过平台视图(Platform View)机制,支持将原生视图嵌入 Flutter。
这一特性,通常用于复用复杂视图,比如 WebView、播放器、地图、游戏引擎画面等。
因为同时涉及到 Android、iOS、Flutter 三个平台,因此需要开发者具备相关平台的知识。
在本文中,对 PlatformView 进行综合介绍。在本章后续文章中,将从使用一直深入到实现原理,做到彻底掌握。后续文章可从侧边栏中浏览。
Android 嵌原生能力
说到 Flutter 的 Platform View 能力,首先想聊的是 Android 平台。这项能力在 Android 上的发展十分曲折,一直以来效果都不理想,受到了诟病。
关于这段曲折发展,具体可参考:《Flutter III 之你不知道的 PlatformView 的混乱之治》
“目前 Flutter 对于嵌原生支持非常混乱。目前3套方案,TLHC、HC、VD 都不是最优解。存在各种兜底策略、历史包袱,因此遇到问题非常难以排查。”
Android 下3种渲染模式
目前,在 Flutter Platform View 在 Android 下,存在 3 套渲染模式,按照代际来分:
代际 | 名称 | 介绍 | 优点 | 缺点 |
---|---|---|---|---|
一 | 虚拟显示模式 Virtual displays VD |
基于 Android VirtualDisplay 机制 将原生视图渲染为纹理 使用 Flutter Texture 渲染 |
不耦合 Flutter 渲染流水线 | 容易有触摸和软键盘兼容性问题 GPU-CPU-GPU 多次内存拷贝,性能开销 |
二 | 混合集成模式 Hybrid composition HC |
将原生视图附加到视图层次结构中 Flutter 视图分层渲染 |
键盘处理、无障碍开箱即用 | Android 10 以前的版本,内存占用变大,绘制性能降低 存在线程竞争问题,容易出现闪烁和卡顿 |
三 | Texture Layer Hybrid Composition TLHC |
FrameLayout 代理 onDraw,替换掉 child 原生控件 Canvas Flutter 3.0 版本引入 |
对普通原生视图支持较好 | 不支持 SurfaceView(播放器、地图) TextureView 支持也不完备,并不总是能正常更新 |
对于封装 Platform View 的开发者来说,需要根据具体场景,选择适合的模式。同时,为了考虑兼容性,还需要兼容其它几种模式。 |
模式并存
在 Flutter 中,3 种模式能并存吗?
由于我尚未对 TLHC 模式开展调研。这里我仅给出部分结论:VD 和 HC 两者是可以并存的。
iOS 下的渲染模式
在 iOS 下仅有一种渲染模式——混合集成模式(Hybrid composition,HC)。
该模式在 iOS 下工作稳定,比较理想,不存在 Android 下这种混乱的情况。
为什么会这样?根据我粗浅的理解,iOS 系统的架构历史悠久,设计更加合理、强大。
附录
以下是我的一些杂乱的草稿,后续会被吸收到其它章节中。
代码实现
《Flutter 内嵌原生视图 Android 端接入实现》
上面从概念上进行了介绍,那如何在 Android 平台下进行代码实现呢?在这篇笔记中记录了对应的代码实现。以及 Flutter 3 之前与之后,对 3 中模式的兼容方式的介绍。点击阅读…
GitHub Issues
- Platform views are drawn at the wrong position and don't fill the parent · Issue #103630 · flutter/flutter
- #103686
- https://github.com/flutter/flutter/issues/104889
- `initSurfaceAndroidView` uses Virtual Display as fallback mode · Issue #107313 · flutter/flutter
- #109690
- #112712
- https://github.com/flutter/flutter/issues/116954
- #130692
- When a PlatformViewLink overlaps another PlatformViewLink, it'll always be on top of the stack. · Issue #136748 · flutter/flutter
- Expose focus control for PlatformViews / connect flutter focus to the platform view level · Issue #141038 · flutter/flutter
性能
在 Flutter 中,平台视图的使用会带来性能上的权衡。
例如,在一个典型的 Flutter 应用中,Flutter UI 是在一个专用的光栅线程上组合的。这使得 Flutter 应用可以快速运行,因为主平台线程很少被阻塞。
当使用混合组合渲染平台视图时,Flutter UI 是从平台线程组合的,这与处理操作系统或插件消息等其他任务竞争资源。
在 Android 10 之前,混合组合模式会将每一帧 Flutter 帧从图形内存复制到主内存,然后再复制回 GPU 纹理。由于这种复制是逐帧发生的,整个 Flutter UI 的性能可能会受到影响。在 Android 10 或更高版本中,图形内存只需复制一次。
另一方面,虚拟显示使原生视图的每个像素都通过额外的中间图形缓冲区流动,这会消耗图形内存和绘图性能。
对于复杂情况,有一些技术可以用来缓解这些问题。
例如,当 Dart 中发生动画时,你可以使用占位符纹理。换句话说,如果在渲染平台视图时动画变慢,那么可以考虑对原生视图进行截图,并将其作为纹理进行渲染。
在使用平台视图时,性能会有影响。具体参见《性能》。
- 纯 Flutter 时,UI 在 raster 线程很少被阻塞,性能高
- 使用平台视图后,引入其他进程竞争
- Android 10 之前:每个 Flutter 帧从显存复制到主内存,再将其复制回 GPU 纹理。两次内存拷贝,导致性能影响
- Android 10 及更高:?
- 平台视图每个像素,都要经过一层缓冲,浪费显存和绘图性能
应用场景
WebView
WebView 是 Flutter 内嵌原生视图能力最常见的场景。WebView 是移动开发中最常使用的控件之一,也是最为复杂的控件之一。在 Flutter 开发中,也需要 WebView 能力。社区中常见的方案,它利用 PlatformView 机制,对 Android、iOS 的 WebView 进行封装,封装为一个 Flutter 组件。开发者在使用时,如同使用纯 Flutter 组件一般,而在底层,是嵌入了原生 WebView 视图能力。
《1.1 使用 Flutter webview_flutter 库引入 WebView 能力》
webview_flutter 是由 Google 官方团队开发的 Flutter WebView,也是社区中的热门选择方案。请参见这篇笔记。
《Flutter webview_flutter Android 端实现原理》
PlatformView 在 Android 下兼容性问题较多,如果你对 Android 端的实现感兴趣,请参见这篇笔记。
除了 webview_flutter 之外,社区中还包含许多第三方开发者的实现,其中不乏高质量者也非常热门。具体可参见这篇笔记。
常见场景
WebView
地图
根据《Flutter 工程化框架选择 — 混合开发的摸爬滚打 · GitBook》不同地图的实现策略:
类型 | 策略 |
---|---|
高德 | 3.0 以下 Virtual displays,3.0 以上 TextureLayer |
华为 | 3.0 以下 Hybrid composition,3.0 以上 Hybrid composition 或者 Texture Layer Hybrid Composition |
百度 | 3.0 以下 Virtual displays,3.0 Texture Layer Hybrid Composition,3.0 以上 Virtual displays 或者 Texture Layer Hybrid Composition |
相关库: |
- tencent_map | Flutter Package:flutter 腾讯地图组件,探索 PlatformView 开发的最佳实践,开发中。
- huawei_map | Flutter Package
- amap_flutter_map | Flutter Package
- flutter_baidu_mapapi_map | Flutter Package
网络资源
platform view:
- 已读:
- 以后读:
- Flutter 3.0 之 PlatformView :告别 VirtualDisplay ,拥抱 TextureLayer - 掘金(归档),讲 TLHC 具体细节的,等后研究到这块再看
- 未读
- Flutter 工程化框架选择 — 混合开发的摸爬滚打 · GitBook
- 不同地图的实现思路差异
- Flutter 深入探索混合开发的技术演进 - 掘金
- Flutter 3.0 之 PlatformView :告别 VirtualDisplay ,拥抱 TextureLayer - 掘金
- Flutter 深入探索混合开发的技术演进 - 掘金
- Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进 - 掘金
- Flutter 1.20 下的 Hybrid Composition 深度解析 - 掘金
- Flutter完整开发实战详解(二十、 Android PlatformView 和键盘问题) - 掘金
- 在 Flutter 应用中使用集成平台视图托管您的原生 iOS 视图 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter
- Flutter 深入探索混合开发的技术演进 - 知乎
- Flutter 3.0 之 PlatformView :告别 VirtualDisplay ,拥抱 TextureLayer - 掘金
- Android Platform Views · flutter/flutter Wiki
- Hosting native Android views in your Flutter app with Platform Views | Flutter
- [Flutter] Platform Viewsの仕組みとパフォーマンス影響を理解して利用する #Flutter - Qiita
- FlutterのPlatformViewを理解する
- Platform Views in Flutter | Play Video in flutter by rendering native views | by Shaik Ahron | Medium
- Flutter で Voice Pococha アプリを1年間開発して感じたこと | BLOG - DeNA Engineering
- Render Video Tracks From WebRTC Using PlatformViews
- The Evolution of Flutter PlatformView | by GSYTech | Medium
- Platform Views for Mobile and Beyond - Dominik Roszkowski Blog
- Fluttter 混合开发下 HybridComposition 和 VirtualDisplay 的实现与未来演进-腾讯云开发者社区-腾讯云
- 二十、 Android PlatformView 和键盘问题-Flutter完整开发实战-教程库-精品编程学习教程库
- TextureLayer class - rendering library - Dart API
- TextureRegistry
- FlutterImageView
- Flutter实战 Textrue和PlatformView_w3cschool
- Flutter AndroidPlatformView - lyuku's blog
- Flutter PlatformView: Creating and Using Platform-Specific Views | by expertappdevs | Jan, 2024 | Medium
- Flutter 3.0 之 PlatformView :告别 VirtualDisplay ,拥抱 TextureLayer · GitBook
- Flutter 工程化框架选择 — 混合开发的摸爬滚打 · GitBook
iOS:
virtual display:
Hybrid Composition:
兼容性:
GitHub Issues:
- [Platform view] Hybrid Composition platform view is invisible on Android < 8 (api 23-24) · Issue #141225 · flutter/flutter
- Android crashes when using Hybrid Composition and Virtual Display widgets simultaneously. · Issue #141565 · flutter/flutter
- [Platform view] Flutter 3.16 regression - Virtual display platform view is invisible on Android < 10 · Issue #141068 · flutter/flutter
StackOverflow:
其他问题反馈:
Flutter WebView:
- flutter_multiple_webview_plugin | Flutter Package
- android - How to Enable Virtual Display in webview_flutter Latest Version? - Stack Overflow
- Adding WebView to your Flutter app | Google Codelabs
- 【Flutter】使用PlatformView显示WebView_flutterplatformview uiwebview-CSDN博客
- packages/webview_flutter - external/github.com/flutter/plugins - Git at Google
- flutter_webview_pro | Flutter Package
地图:
本文作者:Maeiee
本文链接:Flutter 内嵌原生视图能力
版权声明:如无特别声明,本文即为原创文章,版权归 Maeiee 所有,未经允许不得转载!
喜欢我文章的朋友请随缘打赏,鼓励我创作更多更好的作品!